package com.auto.survey.log

import android.content.Context
import java.io.BufferedWriter
import java.io.File
import java.io.FileWriter
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.concurrent.Executors
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.locks.ReentrantLock

class AppLogger private constructor(context: Context) {
    companion object {
        @Volatile
        private var instance: AppLogger? = null

        fun getInstance(context: Context): AppLogger =
            instance ?: synchronized(this) {
                instance ?: AppLogger(context.applicationContext).also { instance = it }
            }

        private const val MAX_STORAGE_DAYS = 10  // 保留10天日志
        private const val MAX_FILE_SIZE_MB = 5  // 单个文件最大5MB
        private const val LOG_FOLDER = "app_logs"
    }

    private val logFolder: File = File(context.filesDir, LOG_FOLDER).apply { mkdirs() }
    private val logQueue = LinkedBlockingQueue<LogEntry>()
    private val executorService = Executors.newSingleThreadExecutor()
    private val fileLock = ReentrantLock()

    init {
        // 启动日志写入线程
        executorService.submit { processLogQueue() }

        // 清理过期日志
        cleanOldLogs()
    }

    // 记录普通日志
    fun v(tag: String, message: String) = enqueueLog(LogLevel.VERBOSE, tag, message)
    fun d(tag: String, message: String) = enqueueLog(LogLevel.DEBUG, tag, message)
    fun i(tag: String, message: String) = enqueueLog(LogLevel.INFO, tag, message)
    fun w(tag: String, message: String) = enqueueLog(LogLevel.WARN, tag, message)
    fun e(tag: String, message: String, throwable: Throwable? = null) {
        val stackTrace = throwable?.stackTraceToString()
        enqueueLog(LogLevel.ERROR, tag, message, stackTrace)
    }

    // 记录崩溃日志
    fun logCrash(throwable: Throwable) {
        enqueueLog(LogLevel.CRASH, "CRASH", throwable.message ?: "Unknown crash", throwable.stackTraceToString())
    }

    // 记录用户操作
    fun logOperation(action: String, details: String = "") {
        enqueueLog(LogLevel.OPERATION, "USER_OP", "$action | $details")
    }

    // 记录内存信息
    fun logMemoryInfo(tag: String = "MEMORY") {
        val runtime = Runtime.getRuntime()
        val totalMemory = runtime.totalMemory()
        val freeMemory = runtime.freeMemory()
        val usedMemory = totalMemory - freeMemory
        val maxMemory = runtime.maxMemory()

        val message = "Used: ${formatSize(usedMemory)}, " +
                "Total: ${formatSize(totalMemory)}, " +
                "Max: ${formatSize(maxMemory)}, " +
                "Free: ${formatSize(freeMemory)}"

        enqueueLog(LogLevel.MEMORY, tag, message)
    }

    // 入队待处理的日志
    private fun enqueueLog(level: LogLevel, tag: String, message: String, stackTrace: String? = null) {
        try {
            logQueue.put(LogEntry(level, tag, message, stackTrace = stackTrace))
        } catch (e: InterruptedException) {
            Thread.currentThread().interrupt()
        }
    }

    // 处理日志队列（后台线程）
    private fun processLogQueue() {
        while (true) {
            try {
                val logEntry = logQueue.take()
                writeLogToFile(logEntry)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    // 写入日志到文件
    private fun writeLogToFile(logEntry: LogEntry) {
        fileLock.lock()
        try {
            val file = getCurrentLogFile()

            // 如果文件超过最大大小，创建新文件
            if (file.exists() && file.length() > MAX_FILE_SIZE_MB * 1024 * 1024) {
                val newFile = createNewLogFile()
                writeLine(newFile, logEntry.toCsv())
            } else {
                writeLine(file, logEntry.toCsv())
            }
        } finally {
            fileLock.unlock()
        }
    }

    // 获取当前日志文件（按日期命名）
    private fun getCurrentLogFile(): File {
        val date = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date())
        return File(logFolder, "app_log_$date.csv")
    }

    // 创建新的日志文件（带序号）
    private fun createNewLogFile(): File {
        val date = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date())
        var index = 1

        while (true) {
            val file = File(logFolder, "app_log_${date}_$index.csv")
            if (!file.exists()) {
                return file
            }
            index++
        }
    }

    // 写入一行内容到文件
    private fun writeLine(file: File, line: String) {
        BufferedWriter(FileWriter(file, true)).use { writer ->
            writer.appendLine(line)
        }
    }

    // 清理过期日志
    private fun cleanOldLogs() {
        executorService.submit {
            fileLock.lock()
            try {
                val threshold = System.currentTimeMillis() - (MAX_STORAGE_DAYS * 24 * 60 * 60 * 1000)

                logFolder.listFiles()?.forEach { file ->
                    val fileDate = extractDateFromFileName(file.name)
                    if (fileDate != null && fileDate.time < threshold) {
                        file.delete()
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                fileLock.unlock()
            }
        }
    }

    // 从文件名提取日期
    private fun extractDateFromFileName(fileName: String): Date? {
        return try {
            val pattern = "app_log_(\\d{4}-\\d{2}-\\d{2})".toRegex()
            val matchResult = pattern.find(fileName)
            val dateStr = matchResult?.groupValues?.get(1) ?: return null
            SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse(dateStr)
        } catch (e: Exception) {
            null
        }
    }

    // 格式化内存大小
    private fun formatSize(bytes: Long): String {
        return if (bytes < 1024) "$bytes B"
        else if (bytes < 1024 * 1024) "${String.format("%.2f", bytes / 1024.0)} KB"
        else "${String.format("%.2f", bytes / (1024.0 * 1024.0))} MB"
    }
}